package com.xci.platform.auth.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import com.xci.platform.annotation.Authorize;
import com.xci.platform.auth.core.AuthConstant;
import com.xci.platform.auth.core.AuthDataSetting;
import com.xci.platform.auth.entity.DepartmentEntity;
import com.xci.platform.auth.entity.ModuleEntity;
import com.xci.platform.auth.service.DepartmentService;
import com.xci.platform.auth.service.ModuleService;
import com.xci.platform.auth.service.RoleService;
import com.xci.platform.auth.service.UserService;
import com.xci.platform.core.BoolMessage;
import com.xci.platform.core.TreeNode;
import com.xci.platform.helper.StringHelper;
import com.xci.platform.controller.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 系统对象资源映射控制器
 */
@Authorize
@Slf4j
@Controller
@RequestMapping("/auth/objectmap")
public class ObjectMapController extends BaseController {
    /**
     * 系统用户服务
     */
    @javax.annotation.Resource
    protected UserService userService;

    /**
     * 角色服务
     */
    @javax.annotation.Resource
    private RoleService roleService;

    /**
     * 模块服务
     */
    @javax.annotation.Resource
    private ModuleService moduleService;

    /**
     * 组织机构服务
     */
    @javax.annotation.Resource
    private DepartmentService departmentService;

    @GetMapping("/setting")
    public String setting(String objectName, String objectId, ModelMap map) {
        AuthDataSetting currentDataSetting = AuthDataSetting.Self;
        currentDataSetting = getAuthDataSetting(objectName, objectId, currentDataSetting);

        map.put("objectName", objectName);
        map.put("objectId", objectId);
        map.put("dataSetting", currentDataSetting);
        return "auth/objectmap/setting";
    }

    @ResponseBody
    @GetMapping("/moduletree")
    public Object moduleTree(String objectName, String objectId) {
        List<ModuleEntity> moduleList;
        Map<String, String> params = new HashMap<>();
        params.put("status", "1");
        List<TreeNode> moduleNodes = moduleService.convertToNodeList(moduleService.query(params));
        List<String> moduleIds = new ArrayList<>();
        switch (objectName) {
            case AuthConstant.Resource.User:
                moduleIds = userService.queryMapModuleIdList(objectId);
                break;
            case AuthConstant.Resource.Role:
                moduleIds = roleService.queryMapModuleIdList(objectId);
                break;
        }
        for (String moduleId : moduleIds) {
            moduleNodes.stream().filter(p -> p.getId().equals(moduleId)).
                    findFirst().ifPresent(treeNode -> treeNode.setChecked(true));
        }
        return BoolMessage.tree(moduleNodes);
    }

    @ResponseBody
    @GetMapping("/departmenttree")
    public Object departmentTree(String objectName, String objectId) {
        List<DepartmentEntity> deptList;
        Map<String, String> params = new HashMap<>();
        params.put("status", "1");
        List<TreeNode> deptNodes = departmentService.convertToNodeList(departmentService.query(params));

        AuthDataSetting dataSetting = AuthDataSetting.Self;
        dataSetting = getAuthDataSetting(objectName, objectId, dataSetting);
        List<String> departmentIds = dataSetting.getCustomData();
        for (String departmentId : departmentIds) {
            deptNodes.stream().filter(p -> p.getId().equals(departmentId))
                    .findFirst().ifPresent(n -> n.setChecked(true));
        }
        return BoolMessage.tree(deptNodes);
    }

    @ResponseBody
    @PostMapping("/save")
    public BoolMessage save(String objectName, String objectId, String moduleIds,
                            String dataType, String departmentIds) {
        AuthDataSetting dataSetting = new AuthDataSetting();
        ReflectUtil.setFieldValue(dataSetting, dataType, true);
        if (dataSetting.isCustom()) {
            dataSetting.setCustomData(CollUtil.toList(StringHelper.splitToArray(departmentIds)));
        }
        BoolMessage result1 =BoolMessage.True;
        BoolMessage result2 =BoolMessage.True;
        switch (objectName) {
            case AuthConstant.Resource.User:
                result1 = userService.saveMapModule(objectId,StringHelper.splitToArray(moduleIds));
                result2 = userService.saveMapDataSetting(objectId,dataSetting);
                break;
            case AuthConstant.Resource.Role:
                result1 = roleService.saveMapModule(objectId,StringHelper.splitToArray(moduleIds));
                result2 = roleService.saveMapDataSetting(objectId,dataSetting);
                break;
        }
        return BoolMessage.merge(result1, result2);
    }

    //region Details
    @ResponseBody
    @GetMapping("/module-details-tree")
    public Object moduleTreeData(String objectName, String objectId) {
        List<ModuleEntity> moduleList = new ArrayList<>();
        switch (objectName) {
            case AuthConstant.Resource.User:
                moduleList = moduleService.queryByUserId(objectId);
                break;
            case AuthConstant.Resource.Role:
                moduleList = moduleService.queryByRoleId(objectId);
                break;
        }
        List<TreeNode> models = moduleService.convertToNodeList(moduleList);
        return BoolMessage.tree(models);
    }

    //endregion

    private AuthDataSetting getAuthDataSetting(String objectName, String objectId, AuthDataSetting currentDataSetting) {
        switch (objectName) {
            case AuthConstant.Resource.User:
                currentDataSetting = userService.queryMapDataSetting(objectId);
                break;
            case AuthConstant.Resource.Role:
                currentDataSetting = roleService.queryMapDataSetting(objectId);
                break;
        }
        return currentDataSetting;
    }
}
